package com.efounder;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
import android.webkit.WebView;

import com.alibaba.android.arouter.launcher.ARouter;
import com.bumptech.glide.Glide;
import com.efounder.constant.EnvironmentVariable;
import com.efounder.frame.language.MultiLanguageUtil;
import com.efounder.util.AppContext;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshFooter;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import com.tencent.bugly.Bugly;
import com.tencent.bugly.crashreport.CrashReport;
import com.utilcode.util.EncryptUtils;
import com.utilcode.util.LogUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;

import static com.efounder.frame.utils.Constants.CHAT_PASSWORD;
import static com.efounder.frame.utils.Constants.CHAT_USER_ID;
import static com.efounder.frame.utils.Constants.KEY_BUGLY_APPID;

public class BaseApplication extends AppContext {
    private static final String TAG = "BaseApplication";
//    public RefWatcher refWatcher;

    //static 代码段可以防止内存泄露
    static {
        initSmartRefreshLayout();
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        sloveAndroidPWebview();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        loadSettingProperties();
        initMutiLanguage();
        initLeakCanry();
        closeAndroidPDialog();
        initArouter();
    }


    protected static void initSmartRefreshLayout() {
        //设置全局的Header构建器
        SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
            @Override
            public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
//                layout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);//全局设置主题颜色
                return new ClassicsHeader(context);//.setTimeFormat(new DynamicTimeFormat("更新于 %s"));//指定为经典Header，默认是 贝塞尔雷达Header
            }
        });
        //设置全局的Footer构建器
        SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
            @Override
            public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
                //指定为经典Footer，默认是 BallPulseFooter
                return new ClassicsFooter(context);
            }
        });
    }

    //加载配置文件，在baseapp 中已经重写
    public void loadSettingProperties() {
    }


    private void initMutiLanguage() {
        if (!shouldInit()) {
            return;
        }

        //多语言工具初始化
        MultiLanguageUtil.init(this);
        //保存系统选择语言
        MultiLanguageUtil.saveSystemCurrentLanguage(this);
        MultiLanguageUtil.setApplicationLanguage(this);
        MultiLanguageUtil.setLocal(this);

    }

    /**
     * 初始化阿里路由框架
     */
    private void initArouter() {
        if (com.efounder.util.LogUtils.isDebugModel(this)) {
            // 这两行必须写在init之前，否则这些配置在init过程中将无效
            // 打印日志
            ARouter.openLog();
            // 开启调试模式(如果在InstantRun模式下运行，必须开启调试模式！线上版本需要关闭,否则有安全风险)
            ARouter.openDebug();
        }
        // 尽可能早，推荐在Application中初始化
        ARouter.init(this);
    }

    private void initLeakCanry() {
        //初始化内存泄露检测工具（正式包中不会包含，不会增加安装包大小）
        //2.0版本以后无需初始化了
//        if (LeakCanary.isInAnalyzerProcess(this)) {
//            refWatcher = RefWatcher.DISABLED;
//        } else {
//            refWatcher = LeakCanary.install(this);
//        }
    }

    /**
     * 初始化bugly baseapp中调用的
     */
    protected void initBugly() {
        //import static com.efounder.frame.utils.Constants.KEY_BUGLY_APPID;
        Bugly.init(this, EnvironmentVariable.getProperty(KEY_BUGLY_APPID), false);
        //加密部分信息后上传
        CrashReport.putUserData(this, "userId", EnvironmentVariable.getUserName());
        //16位key
        String randomKey = "ghtuaelhtuiahfji";
        if (!TextUtils.isEmpty(EnvironmentVariable.getPassword())) {
            String secretPassword = EncryptUtils.encryptAES2HexString(EnvironmentVariable.getPassword().getBytes(),
                    randomKey.getBytes(), "AES/ECB/PKCS5Padding", null);
            CrashReport.putUserData(this, "auth", secretPassword);
        }
        CrashReport.putUserData(this, "imId", EnvironmentVariable.getProperty(CHAT_USER_ID));
        if (!TextUtils.isEmpty(EnvironmentVariable.getProperty(CHAT_PASSWORD))) {
            String secretImPass = EncryptUtils.encryptAES2HexString(EnvironmentVariable.getProperty(CHAT_USER_ID).getBytes(),
                    randomKey.getBytes(), "AES/ECB/PKCS5Padding", null);
            CrashReport.putUserData(this, "ImAuth", secretImPass);
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // 横竖屏切换时调用
        MultiLanguageUtil.onConfigurationChanged(getApplicationContext());
    }

//    public static RefWatcher getRefWatcher(Context context1) {
//        BaseApplication application = (BaseApplication) context1.getApplicationContext();
//        return application.refWatcher;
//    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        super.onTrimMemory(level);
        switch (level) {
//TRIM_MEMORY_UI_HIDDEN 表示应用程序的所有UI界面被隐藏了，即用户点击了Home键或者Back键导致应用的UI界面不可见．这时候应该释放一些资源
            case Activity.TRIM_MEMORY_UI_HIDDEN:

                break;
//TRIM_MEMORY_RUNNING_MODERATE 表示应用程序正常运行，并且不会被杀掉。但是目前手机的内存已经有点低了，系统可能会开始根据LRU缓存规则来去杀死进程了。
            case Activity.TRIM_MEMORY_RUNNING_MODERATE:
                break;
//TRIM_MEMORY_RUNNING_LOW 表示应用程序正常运行，并且不会被杀掉。但是目前手机的内存已经非常低了，我们应该去释放掉一些不必要的资源以提升系统的性能，同时这也会直接影响到我们应用程序的性能。
            case Activity.TRIM_MEMORY_RUNNING_LOW:
                break;
//TRIM_MEMORY_RUNNING_CRITICAL 表示应用程序仍然正常运行，但是系统已经根据LRU缓存规则杀掉了大部分缓存的进程了。这个时候我们应当尽可能地去释放任何不必要的资源，不然的话系统可能会继续杀掉所有缓存中的进程，并且开始杀掉一些本来应当保持运行的进程，比如说后台运行的服务。
            case Activity.TRIM_MEMORY_RUNNING_CRITICAL:
                break;
//当应用程序是缓存的，则会收到以下几种类型的回调：
//TRIM_MEMORY_BACKGROUND 表示手机目前内存已经很低了，系统准备开始根据LRU缓存来清理进程。这个时候我们的程序在LRU缓存列表的最近位置，是不太可能被清理掉的，但这时去释放掉一些比较容易恢复的资源能够让手机的内存变得比较充足，从而让我们的程序更长时间地保留在缓存当中，这样当用户返回我们的程序时会感觉非常顺畅，而不是经历了一次重新启动的过程。
            case Activity.TRIM_MEMORY_BACKGROUND:
                break;
//TRIM_MEMORY_MODERATE 表示手机目前内存已经很低了，并且我们的程序处于LRU缓存列表的中间位置，如果手机内存还得不到进一步释放的话，那么我们的程序就有被系统杀掉的风险了。
            case Activity.TRIM_MEMORY_MODERATE:
                //释放glide内存缓存
                clearGlideMemoryCache();
                break;
//TRIM_MEMORY_COMPLETE 表示手机目前内存已经很低了，并且我们的程序处于LRU缓存列表的最边缘位置，系统会最优先考虑杀掉我们的应用程序，在这个时候应当尽可能地把一切可以释放的东西都进行释放。
            case Activity.TRIM_MEMORY_COMPLETE:

                break;
            default:

                break;
        }
    }

    //释放glide内存缓存
    private void clearGlideMemoryCache() {
        LogUtils.i("内存不足，glide清除内存缓存");
        try {
            Glide.get(this).clearMemory();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 隐藏android p 弹出的提示
     * https://www.jianshu.com/p/f87fe39caf1d?tdsourcetag=s_pctim_aiomsg
     */
    private void closeAndroidPDialog() {
        try {
            Class aClass = Class.forName("android.content.pm.PackageParser$Package");
            Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class);
            declaredConstructor.setAccessible(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Class cls = Class.forName("android.app.ActivityThread");
            Method declaredMethod = cls.getDeclaredMethod("currentActivityThread");
            declaredMethod.setAccessible(true);
            Object activityThread = declaredMethod.invoke(null);
            Field mHiddenApiWarningShown = cls.getDeclaredField("mHiddenApiWarningShown");
            mHiddenApiWarningShown.setAccessible(true);
            mHiddenApiWarningShown.setBoolean(activityThread, true);
        } catch (Exception e) {
//            e.printStackTrace();
        }
    }


    /**
     * 是否需要初始化（在主进程返回true）
     *
     * @return
     */
    public boolean shouldInit() {
        ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
        List<ActivityManager.RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();
        String mainProcessName = getPackageName();
        int myPid = android.os.Process.myPid();

        for (ActivityManager.RunningAppProcessInfo info : processInfos) {
//            Log.i(TAG, "my.pid -> " + myPid + ",mainProcessName -> " + mainProcessName);
//            Log.i(TAG, "info.pid -> " + info.pid + ",info.processName -> " + info.processName);

            if (info.pid == myPid && mainProcessName.equals(info.processName)) {
                return true;
            }
        }
        return false;
    }


    private void sloveAndroidPWebview() {
        webviewSetPath();
    }

    /**
     * Android P 以及之后版本不支持同时从多个进程使用具有相同数据目录的WebView
     * https://www.jianshu.com/p/9d0cd219d982
     * 为其它进程webView设置目录
     */
    public void webviewSetPath() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {

            String mainProcessName = getPackageName();
            String currentProcessName = getProcessName(this);
            //判断不等于默认进程名称
            if (!currentProcessName.equals(mainProcessName)) {
                Log.e(TAG, " WebView.setDataDirectorySuffix" + currentProcessName);
                WebView.setDataDirectorySuffix(currentProcessName);
            }
        }
    }

    public String getProcessName(Context context) {
        if (context == null) return null;
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
            if (processInfo.pid == android.os.Process.myPid()) {
                return processInfo.processName;
            }
        }
        return null;
    }

}
